package com.prb.consumer.proxy;

import com.prb.common.protocol.RpcRequest;
import com.prb.common.protocol.RpcResponse;
import com.prb.consumer.config.Client;
import com.prb.consumer.config.ClientContext;
import io.netty.channel.ChannelPromise;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

public class RpcConsumer<T> {

    public static RpcConsumer instance = new RpcConsumer();

    public static Map<String, RpcResponse> responseMap = new ConcurrentHashMap<>();

    public Object getProxy(Class<T> cls) {

        return Proxy.newProxyInstance(RpcConsumer.class.getClassLoader(), new Class[]{(Class<T>) cls}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                String requestId = allotRequestId(cls);

                RpcRequest rpcRequest = getRpcRequest(method, args, requestId, cls);

                responseMap.put(requestId, new RpcResponse(requestId, Thread.currentThread(), null));

                Client client = ClientContext.allotClient(cls.getName());
                while(client == null){
                    client = ClientContext.allotClient(cls.getName());

                }

                ChannelPromise channelPromise = client.send(rpcRequest);
                channelPromise.get();
                //线程锁定
                //LockSupport.park();

                return responseMap.remove(requestId).getResult();
            }

            private String allotRequestId(Class<T> cls) {

                return cls.getName() + ":" + UUID.randomUUID().toString();
            }
        });
    }

    private RpcRequest getRpcRequest(Method method, Object[] args, String requestId, Class<T> cls) {
        RpcRequest rpcRequest = new RpcRequest();
        rpcRequest.setInvokeId(requestId);
        rpcRequest.setArgs(Arrays.asList(args));
        rpcRequest.setParamTypes(method.getParameterTypes());
        rpcRequest.setClazz(cls);
        rpcRequest.setMethodName(method.getName());
        return rpcRequest;
    }
}
/*  重试代码
        try{
                int time = 5;
                while(time > 0){
                try {
                Client client = ClientContext.allotClient(cls.getName());
                client.send(rpcRequest);
                break;

                }catch (Exception e){
                System.out.println("error msg is : " + e.getMessage());
                System.out.println("连接断开================================");
                time--;
                }
                }
*/
